home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / telecomm / uwsrc.arc / WINHASH.C < prev    next >
C/C++ Source or Header  |  1989-04-29  |  7KB  |  312 lines

  1. /*
  2.  * This file contains routines which can be used to determine the character
  3.  * present at a given location in a window.  These functions are used to
  4.  * determine the character under the mouse cursor, and for the log-top printer
  5.  * function.
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <osbind.h>
  10. #include "windefs.h"
  11.  
  12. extern struct wi_str w[];
  13.  
  14. int    highlighted_wdes = -1;    /* make this global now for use in winmain.c*/
  15.  
  16. /*
  17.  * char_at returns the ascii code of the character in wdes window at
  18.  * (x_loc, y_loc) cursor position.  Zero is returned if the character can
  19.  * not be identified.
  20.  */
  21. int char_at(wdes, x_loc, y_loc)
  22. int wdes, x_loc, y_loc;
  23.  
  24. {
  25.  
  26.   register struct wi_str *wp = &w[wdes];
  27.   int ch, width, boffset, count, cur_y, cur_x;
  28.   register unsigned long mask;
  29.   register unsigned long *dptr;
  30.   register int shift;
  31.   register FNT *fnt = wp->font;
  32.   static char pa[32];         /* pixel array containing character image */
  33.   
  34.   cur_x = x_loc * fnt->inc_x + X0;
  35.   cur_y = y_loc * fnt->inc_y + wp->top_y;
  36.   
  37.   width = 2 * wp->wi_mf.wwords;
  38.   boffset = wp->m_off+cur_x+fnt->inc_x-1;
  39.   dptr = ((char *)(wp->wi_mf.ptr)) + cur_y * width
  40.     + ((boffset >> 4) << 1) - 2;
  41.   shift = 15 - (boffset & 15);
  42.   mask = (-1L<<(shift+fnt->inc_x)|(1<<shift)-1);
  43.   for (count = 0; count < fnt->inc_y; count ++)
  44.   {
  45.     pa[count] = (*dptr & (~ mask)) >> shift;
  46.     ((char *) dptr) += width;
  47.   }
  48.   
  49.   ch = which_char(fnt, &fnt->f_hash, pa);
  50.   if (ch == 0)        /* Not found, check for inverse vidio case */
  51.   {
  52.     for (count = 0; count < fnt->inc_y; count ++)
  53.       pa[count] = ~pa[count] & (1<< fnt->inc_x) - 1;
  54.     ch = which_char(fnt, &fnt->f_hash, pa);
  55.   }
  56.   return (ch);
  57. }
  58.  
  59. /*
  60.  * which_char returns the ascii code of the character bitmap in pa from font
  61.  * font using hash table htbl.
  62.  */
  63. int which_char(font, htbl, pa)
  64. FNT *font;
  65. HTBL *htbl;
  66. char *pa;
  67.  
  68. {
  69.   register int i, h, n;
  70.   
  71.   h = hash_char (pa, font->inc_y);
  72.   if ((htbl->h_t[h] & 128) == 0) /* collision bit set? */
  73.   {
  74.     for (i=0; i<font->inc_y; i++)
  75.       if (font->f_data[(htbl->h_t)[h] * 16 + i] != pa[i])
  76.         break;
  77.     if (i < font->inc_y){
  78.       return 0;
  79.     }
  80.     else
  81.       return (htbl->h_t[h]);
  82.   }
  83.   else                /* collision, search colision list for char */
  84.   {
  85.     n = htbl->h_t[h] & 127;
  86.     while (n != 0)
  87.     {
  88.       for (i=0; i<font->inc_y; i++)
  89.         if (font->f_data[(htbl->h_colision)[n].h_try * 16 + i] != pa[i])
  90.       break;
  91.       if (i < font->inc_y)
  92.         n = htbl->h_colision[n].h_next;
  93.       else
  94.         return (htbl->h_colision[n].h_try);
  95.     }
  96.     return 0;
  97.   }
  98. }
  99.  
  100. /*
  101.  * gen_hash initalizes htbl with the hash table for font font.
  102.  */
  103. void gen_hash(font, htbl)
  104. FNT *font;
  105. HTBL *htbl;
  106.  
  107. {
  108.   register int overflowcnt = 1;
  109.   register int np, tp, i, j;
  110.   int h;
  111.   
  112.   for (i=0; i<128; i++)        /* initalize */
  113.     htbl->h_colision[i].h_next = '\0';
  114.   for (i=0; i<(1<<HASHBITS); i++)
  115.     htbl->h_t[i] = '\0';
  116.   
  117.   for (i=32; i<128; i++)
  118.   {            /* for each character */
  119.     h = hash_char(&font->f_data[i*16], font->inc_y);
  120.     if (htbl->h_t[h] == 0)
  121.       htbl->h_t[h] = i;
  122.     else
  123.     {
  124.       if ((htbl->h_t[h] & 128) == 0) /* already overflowed? */
  125.       { /* No, move first element to overflow list */
  126.     htbl->h_colision[overflowcnt].h_try = htbl->h_t[h];
  127.         htbl->h_t[h] = 128 | overflowcnt;
  128.     overflowcnt++;
  129.       }
  130.     
  131.       tp = htbl->h_t[h] & 127;
  132.       j=0;    /* dbug */
  133.       while ((np = htbl->h_colision[tp].h_next) != 0){
  134.     tp = np;
  135.     j++; /* dbug */
  136.       }
  137. #ifdef DEBUG
  138.       printf("overflow=%d depth=%d hash %d = %d\n",overflowcnt, j, i, h);
  139. #endif
  140.       htbl->h_colision[tp].h_next = overflowcnt;
  141.       htbl->h_colision[overflowcnt].h_try = i;
  142.       ++ overflowcnt;
  143.     }
  144.   }
  145.  
  146. #ifdef DEBUG     /* verify sanity of hash table */
  147.   for (i=32; i<128; i++) /* dbug */
  148.     if ((j = which_char(font, htbl, &font->f_data[i*16])) != i)
  149.   {
  150.     printf("%d != %d\n", i, j);
  151.   }
  152. #endif
  153. }
  154.  
  155. /*
  156.  * hash_char returns the hash code for the character pixel image in pa of
  157.  * height height.
  158.  */
  159. int hash_char(pa, height)
  160. char *pa;
  161. int height;
  162.  
  163. {
  164.   register int h, i, j;
  165.   
  166.   h=0;
  167.   for (i=0; i<height; i++)
  168.   {
  169.     h += pa[i] << i*3 % HASHBITS;
  170.   }
  171.   j = (1<<HASHBITS) - 1;
  172.   h = (h + (h >> HASHBITS + 1)) & j;
  173.  
  174.   return h;
  175. }
  176.  
  177. /*
  178.  * dump_line send the y_coord'th line in the window wdes to the printer.
  179.  * zero is returned if the line was printed ok.
  180.  */
  181. dump_line(wdes, y_coord)
  182. {
  183.   int i;
  184.   char ch;
  185.   
  186.   for (i = 0; i < w[wdes].x_chrs; i++){
  187.     ch = char_at(wdes, i, y_coord);
  188.     if (Cprnout(ch) == 0) {
  189.       w[wdes].ptr_status = LOG_NONE;
  190.       return -1;
  191.     }
  192.   }
  193.   if (Cprnout('\n') == 0 | Cprnout('\r') == 0) {
  194.     w[wdes].ptr_status = LOG_NONE;
  195.     return -1;
  196.   }
  197.   return 0;
  198. }
  199.  
  200. /*
  201.  * dump_window send the contents of wdes to the printer.
  202.  */
  203. dump_window(wdes)
  204. {
  205.   int i;
  206.   
  207.   for (i = 0; i < w[wdes].y_chrs; i++){
  208.     dump_line(wdes, i);
  209.   }
  210. }
  211. /* copy_word fills buffer with the word at (x1, y1) from wdes
  212.  * No checks are made for buffer overflow.
  213.  */
  214. copy_word(wdes, x1, y1, buffer)
  215. int wdes, x1, y1;
  216. char * buffer;
  217. {
  218.   register int fx, lx, yo, xo;
  219.   
  220.   yo = w[wdes].y_off / w[wdes].font->inc_y; /* adjust for scroll bar action */  
  221.   xo = w[wdes].x_off / w[wdes].font->inc_x;
  222.   fx = x1 - 1;
  223.   lx = x1 + 1;
  224.   
  225.   while (fx + xo >= 0 && char_at(wdes, fx + xo, y1 + yo) != ' ')
  226.     --fx;
  227.   while (lx + xo < w[wdes].x_chrs && char_at(wdes, lx + xo, y1 + yo) != ' ')
  228.     ++lx;
  229.   copy_text(wdes, ++fx, y1, --lx, y1, buffer);
  230. }
  231.  
  232. /* copy_text fills buffer with the text between (x1, y1) and (x2, y2) from wdes
  233.  * where point 1 is before point 2.  No checks are made for buffer overflow.
  234.  */
  235. copy_text(wdes, x1, y1, x2, y2, buffer)
  236. int wdes, x1, y1, x2, y2;
  237. char * buffer;
  238. {
  239.   static int old_hh;
  240.   static int old_y1;
  241.   register int cx, cy, i, lastnbi, lastnbx;
  242.   int inc_y, inc_x, top_y;
  243.  
  244.   /* undo any old selected text which might be inverted on screen */
  245.   if (highlighted_wdes > 0 && w[highlighted_wdes].font != NULL)
  246.   {
  247.     w_update(highlighted_wdes, FM_COPY, 0, old_y1,
  248.       w[highlighted_wdes].x_chrs * w[highlighted_wdes].font->inc_x + X0 + 1,
  249.       old_hh);
  250.   }
  251.   if (y1 > y2) return;    /* nothing to do */
  252.  
  253.   inc_y = w[wdes].font->inc_y;
  254.   inc_x = w[wdes].font->inc_x;
  255.   top_y = w[wdes].top_y;
  256.     
  257.   y1 = y1 + w[wdes].y_off / inc_y;    /* adjust for scroll bar action */  
  258.   y2 = y2 + w[wdes].y_off / inc_y;    /* assumes _off is multiple of inc_ */
  259.   x1 = x1 + w[wdes].x_off / inc_x;
  260.   x2 = x2 + w[wdes].x_off / inc_x;
  261.   i = 0;
  262.   lastnbi = 0;
  263.   lastnbx = x1;
  264.  
  265.   if (y1 > y2)
  266.   {
  267.     highlighted_wdes = -1;    /* no undo required on next call */
  268.     return;
  269.   }
  270.   
  271.   old_y1 = y1 * inc_y + top_y;
  272.   old_hh = (y2 - y1 + 2) * inc_y + Y0;
  273.   highlighted_wdes = wdes;
  274.   
  275.   cx = x1;
  276.   cy = y1;
  277.  
  278.   while (cy < y2 || (cy == y2 && cx <= x2))
  279.   {
  280.     buffer[i] = char_at(wdes, cx, cy);
  281.     if (buffer[i] != ' ')
  282.     {
  283.       lastnbi = i;
  284.       lastnbx = cx;
  285.     }
  286.     cx ++;
  287.     if (cx >= w[wdes].x_chrs)
  288.     {
  289.       if (cy == y1)    /* first line */
  290.         w_update(wdes, FM_INVERT, x1 * inc_x, cy * inc_y + top_y,
  291.       (++lastnbx - x1) * inc_x + X0, inc_y);
  292.       else
  293.         w_update(wdes, FM_INVERT, 0, cy * inc_y + top_y,
  294.       ++lastnbx * inc_x + X0, inc_y);
  295.       cx = 0;
  296.       cy ++;
  297.       i = ++lastnbi;
  298.       lastnbx = -1;
  299.       buffer[i] = '\r';
  300.     }
  301.     i++;
  302.   }
  303.   if (cy == y1)    /* one line */
  304.     w_update(wdes, FM_INVERT, x1 * inc_x, cy * inc_y + top_y,
  305.       (++lastnbx - x1) * inc_x + X0, inc_y);
  306.   else
  307.     w_update(wdes, FM_INVERT, 0, cy * inc_y + top_y,
  308.       ++lastnbx * inc_x + X0, inc_y);
  309.   buffer[++lastnbi] = '\0';
  310. }
  311.  
  312.